#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>  // 用于字符检查
#include <wchar.h>  // 用于处理宽字符（中文字符）
#include <locale.h> // 用于设置本地化环境，支持中文字符

typedef struct {
    int id;
    char name[50];  // 名字长度限制为50
    float *scores;  // 动态分配科目成绩数组
    int failed_subjects;
} Student;

// 函数声明
int is_valid_name(const char *name);
void add_student(Student students[], int *count, int max_students, int max_subjects);
void delete_student(Student students[], int *count, int id);
void modify_student(Student students[], int count, int id);
void add_score(Student students[], int count, int id, int max_subjects);
void rank_students(Student students[], int count, int subject_index, int max_subjects);
void query_student_scores(Student students[], int count, int id, int max_subjects);
void list_failed_students(Student students[], int count, int max_subjects);
void free_students(Student students[], int count);  // 释放动态分配的内存

int main() {
    setlocale(LC_ALL, ""); // 设置本地化环境，支持中文字符
    const int MAX_STUDENTS = 100;  // 最大学生数量
    const int MAX_SUBJECTS = 4;    // 最大科目数量
    Student students[MAX_STUDENTS];
    int count = 0;
    int choice, id, subject_index;

    while (1) {
        printf("\n学生成绩管理系统\n");
        printf("1. 添加学生\n");
        printf("2. 删除学生\n");
        printf("3. 修改学生信息\n");
        printf("4. 录入单科成绩\n");
        printf("5. 班级内单科成绩排名\n");
        printf("6. 查询学生成绩\n");
        printf("7. 统计不及格科目超过2科的学生名单\n");
        printf("8. 退出\n");
        printf("请选择操作: ");
        scanf("%d", &choice);

        switch (choice) {
            case 1:
                add_student(students, &count, MAX_STUDENTS, MAX_SUBJECTS);
                break;
            case 2:
                printf("请输入要删除的学生ID: ");
                scanf("%d", &id);
                delete_student(students, &count, id);
                break;
            case 3:
                printf("请输入要修改的学生ID: ");
                scanf("%d", &id);
                modify_student(students, count, id);
                break;
            case 4:
                printf("请输入要录入成绩的学生ID: ");
                scanf("%d", &id);
                add_score(students, count, id, MAX_SUBJECTS);
                break;
            case 5:
                printf("请输入要排名的科目索引 (0: 数学, 1: 语文, 2: 英语, 3: 体育): ");
                scanf("%d", &subject_index);
                rank_students(students, count, subject_index, MAX_SUBJECTS);
                break;
            case 6:
                printf("请输入要查询的学生ID: ");
                scanf("%d", &id);
                query_student_scores(students, count, id, MAX_SUBJECTS);
                break;
            case 7:
                list_failed_students(students, count, MAX_SUBJECTS);
                break;
            case 8:
                free_students(students, count);  // 释放动态分配的内存
                exit(0);
            default:
                printf("无效的选择，请重新输入。\n");
        }
    }

    return 0;
}

// 检查输入是否合法
int is_valid_name(const char *name) {
    for (int i = 0; name[i] != '\0'; i++) {
        // 允许字母、空格和中文字符
        if (!isalpha(name[i]) && name[i] != ' ' && !(name[i] & 0x80)) {
            return 0;  // 非法字符
        }
    }
    return 1;  // 合法
}

void add_student(Student students[], int *count, int max_students, int max_subjects) {
    if (*count >= max_students) {
        printf("学生数量已达上限，无法添加新学生。\n");
        return;
    }

    Student new_student;
    new_student.id = *count + 1;

    while (1) {
        printf("请输入学生姓名: ");
        scanf("%s", new_student.name);

        if (is_valid_name(new_student.name)) {
            break;  // 输入合法，退出循环
        } else {
            printf("输入包含非法字符或数字，请重新输入。\n");
        }
    }

    // 动态分配科目成绩数组
    new_student.scores = (float *)malloc(max_subjects * sizeof(float));
    if (new_student.scores == NULL) {
        printf("内存分配失败，无法添加学生。\n");
        return;
    }

    for (int i = 0; i < max_subjects; i++) {
        new_student.scores[i] = -1; // -1 表示未录入成绩
    }
    new_student.failed_subjects = 0;

    students[*count] = new_student;
    (*count)++;
    printf("学生添加成功，ID为 %d。\n", new_student.id);
}

void delete_student(Student students[], int *count, int id) {
    int found = 0;
    for (int i = 0; i < *count; i++) {
        if (students[i].id == id) {
            found = 1;
            free(students[i].scores);  // 释放动态分配的内存
            for (int j = i; j < *count - 1; j++) {
                students[j] = students[j + 1];
            }
            (*count)--;
            printf("学生删除成功。\n");
            break;
        }
    }
    if (!found) {
        printf("未找到该学生。\n");
    }
}

void modify_student(Student students[], int count, int id) {
    int found = 0;
    for (int i = 0; i < count; i++) {
        if (students[i].id == id) {
            found = 1;
            while (1) {
                printf("请输入新的学生姓名: ");
                scanf("%s", students[i].name);

                if (is_valid_name(students[i].name)) {
                    break;  // 输入合法，退出循环
                } else {
                    printf("输入包含非法字符或数字，请重新输入。\n");
                }
            }
            printf("学生信息修改成功。\n");
            break;
        }
    }
    if (!found) {
        printf("未找到该学生。\n");
    }
}

void add_score(Student students[], int count, int id, int max_subjects) {
    int found = 0;
    for (int i = 0; i < count; i++) {
        if (students[i].id == id) {
            found = 1;
            for (int j = 0; j < max_subjects; j++) {
                const char *subject_name;
                switch (j) {
                    case 0: subject_name = "数学"; break;
                    case 1: subject_name = "语文"; break;
                    case 2: subject_name = "英语"; break;
                    case 3: subject_name = "体育"; break;
                    default: subject_name = "未知科目"; break;
                }

                while (1) {
                    printf("请输入%s的成绩: ", subject_name);
                    float score;
                    int result = scanf("%f", &score);

                    if (result == 1) {
                        // 检查成绩是否在 0-100 范围内
                        if (score >= 0 && score <= 100) {
                            students[i].scores[j] = score;
                            if (students[i].scores[j] < 60) {
                                students[i].failed_subjects++;
                            }
                            break; // 输入有效，退出循环
                        } else {
                            printf("输入无效，成绩必须在 0 到 100 之间。\n");
                        }
                    } else {
                        printf("输入无效，请输入一个数字。\n");
                        // 清空输入缓冲区，避免无效输入影响后续操作
                        while (getchar() != '\n'); // 清除缓冲区中的无效字符
                    }
                }
            }
            printf("成绩录入成功。\n");
            break;
        }
    }
    if (!found) {
        printf("未找到该学生。\n");
    }
}

void rank_students(Student students[], int count, int subject_index, int max_subjects) {
    if (subject_index < 0 || subject_index >= max_subjects) {
        printf("无效的科目索引。\n");
        return;
    }

    const char *subject_name;
    switch (subject_index) {
        case 0: subject_name = "数学"; break;
        case 1: subject_name = "语文"; break;
        case 2: subject_name = "英语"; break;
        case 3: subject_name = "体育"; break;
        default: subject_name = "未知科目"; break;
    }

    Student temp[count];
    memcpy(temp, students, count * sizeof(Student));

    for (int i = 0; i < count - 1; i++) {
        for (int j = 0; j < count - i - 1; j++) {
            if (temp[j].scores[subject_index] < temp[j + 1].scores[subject_index]) {
                Student swap = temp[j];
                temp[j] = temp[j + 1];
                temp[j + 1] = swap;
            }
        }
    }

    printf("%s 的成绩排名:\n", subject_name);
    for (int i = 0; i < count; i++) {
        printf("第 %d 名: 学生ID %d, 姓名 %s, 成绩 %.2f\n", i + 1, temp[i].id, temp[i].name, temp[i].scores[subject_index]);
    }
}

void query_student_scores(Student students[], int count, int id, int max_subjects) {
    int found = 0;
    for (int i = 0; i < count; i++) {
        if (students[i].id == id) {
            found = 1;
            printf("学生ID: %d, 姓名: %s\n", students[i].id, students[i].name);
            for (int j = 0; j < max_subjects; j++) {
                const char *subject_name;
                switch (j) {
                    case 0: subject_name = "数学"; break;
                    case 1: subject_name = "语文"; break;
                    case 2: subject_name = "英语"; break;
                    case 3: subject_name = "体育"; break;
                    default: subject_name = "未知科目"; break;
                }
                printf("%s 成绩: %.2f\n", subject_name, students[i].scores[j]);
            }
            break;
        }
    }
    if (!found) {
        printf("未找到该学生。\n");
    }
}

void list_failed_students(Student students[], int count, int max_subjects) {
    printf("不及格科目超过2科的学生名单:\n");
    for (int i = 0; i < count; i++) {
        if (students[i].failed_subjects > 2) {
            printf("学生ID: %d, 姓名: %s, 不及格科目数: %d\n", students[i].id, students[i].name, students[i].failed_subjects);
        }
    }
}

void free_students(Student students[], int count) {
    for (int i = 0; i < count; i++) {
        free(students[i].scores);  // 释放每个学生的科目成绩数组
    }
}
